//
//  JKTool.swift
//  JKTool
//
//  Created by 姜奎 on 2021/4/25.
//

import Darwin
import Foundation

struct JKTool: ParsableCommand {
    static var configuration = CommandConfiguration(
        commandName: "jktool",
        abstract: "jktool",
        version: "1.0.0",
        subcommands: [Modules.self,
                      Build.self,
                      Build.Clean.self,
                      Archive.self,
                      Export.self,
                      Upload.self,
                      IpaParse.self,
                      IpaCompare.self,
                      Git.self,
                      Config.self,
                      Shell.self,
                      Zipper.self,
                      Gif.self,
                      VideoSnapshotter.self,
                      ImageStitcher.self,
                      UNZipper.self,
                      ToolDictionary.self,
                      ToolArray.self,
                      Open.self,
                      ToolVersion.self,
                      HBBiz.self])
}

extension JKTool {
    struct ToolVersion: ParsableCommand {
        static var configuration = CommandConfiguration(
            commandName: "version",
            abstract: "JKTool检查更新",
            subcommands: [Update.self, Reset.self],
            defaultSubcommand: Update.self)
    }

    static func append(_ newContents: String, userDirectoryBy fileName: String) {
        let filePath = URL(fileURLWithPath: "\(FileManager.userDirectory())/\(fileName)")

        let fileData = try? Data(contentsOf: filePath)


        var file = String(data: fileData ?? Data(), encoding: .utf8) ?? ""

        let lines = file.components(separatedBy: .newlines)

        var modifiedLines: [String] = []
        for line in lines {
            if line.contains("jktool") || line.contains("JKTool") {
                continue
            } else {
                    // 否则保持原样
                modifiedLines.append(line)
            }
        }

        modifiedLines.append(newContents)

        file = modifiedLines.joined(separator: "\n")

        do {
            try file.write(to: filePath, atomically: true, encoding: .utf8)
            po(tip: "【JKTool】\(fileName)写入`\(filePath)`成功")
        } catch {
            po(tip: "【JKTool】\(fileName)写入`\(filePath)`失败：\n" + error.localizedDescription,type: .warning)
        }
    }
}

extension JKTool.ToolVersion {
    struct Update: ParsableCommand {
        static var configuration = CommandConfiguration(
            commandName: "update",
            _superCommandName: "version",
            abstract: "JKTool脚本检查更新",
            version: "1.0.0")

        mutating func run() {

            func downloadTool() -> Bool {
                guard let toolUrl = URL(with: ModulesConfigs.sharedInstance.config.toolUrl) else {
                    po(tip: "【JKTool】jktool下载路径转换失败，请检查路径是否有效(\(ModulesConfigs.sharedInstance.config.toolUrl))",type: .warning)
                    return false
                }

                po(tip: "【JKTool】jktool开始下载(\(ModulesConfigs.sharedInstance.config.toolUrl))")

                guard let data = try? Data(contentsOf: toolUrl) else {
                    po(tip: "【JKTool】jktool download失败",type: .warning)
                    return false
                }

                if !FileManager.default.fileExists(atPath: ModulesConfigs.documentBinPath) {
                    try? FileManager.default.createDirectory(atPath: ModulesConfigs.documentBinPath, withIntermediateDirectories: true)
                }

                let toolDocumentTargetPath = "\(ModulesConfigs.documentBinPath)/jktool"
                try? FileManager.default.removeItem(atPath: toolDocumentTargetPath)

                do {
                    _ = try data.write(to: URL(fileURLWithPath: toolDocumentTargetPath), options: .atomicWrite)
                    try FileManager.default.setAttributes([FileAttributeKey.posixPermissions: 0o777], ofItemAtPath: toolDocumentTargetPath)
                    po(tip: "【JKTool】jktool下载成功",type: .tip)
                } catch {
                    po(tip: "【JKTool】jktool下载失败：\n" + error.localizedDescription,type: .warning)
                    return false
                }

                let linkDirectoryPath = FileManager.userDirectory() + "/.JKTool"

                if !FileManager.default.fileExists(atPath: linkDirectoryPath) {
                    try? FileManager.default.createDirectory(atPath: linkDirectoryPath, withIntermediateDirectories: true)
                }

                let toolLinkPath = "\(linkDirectoryPath)/jktool"
                try? FileManager.default.removeItem(atPath: toolLinkPath)

                do {
                    try FileManager.default.createSymbolicLink(atPath: toolLinkPath, withDestinationPath: toolDocumentTargetPath)
                    po(tip: "【JKTool】jktool link成功",type: .tip)
                    return true
                } catch {
                    po(tip: "【JKTool】jktool link失败：\n" + error.localizedDescription,type: .warning)
                    return false
                }
            }

            func downloadToolZshCompletion() {
                guard let zshCompletionUrl = URL(with: ModulesConfigs.sharedInstance.config.zshCompletionUrl) else {
                    return po(tip: "【JKTool】jktool-zsh下载路径转换失败，请检查路径是否有效(\(ModulesConfigs.sharedInstance.config.zshCompletionUrl))",type: .warning)
                }

                po(tip: "【JKTool】jktool-zsh开始下载(\(ModulesConfigs.sharedInstance.config.zshCompletionUrl))")

                guard let data = try? Data(contentsOf: zshCompletionUrl) else {
                    return po(tip: "【JKTool】jktool-zsh download失败",type: .warning)
                }

                if !FileManager.default.fileExists(atPath: ModulesConfigs.documentZshSharePath) {
                    try? FileManager.default.createDirectory(atPath: ModulesConfigs.documentZshSharePath, withIntermediateDirectories: true)
                }

                let zshCompletionPath = "\(ModulesConfigs.documentZshSharePath)/_jktool"
                try? FileManager.default.removeItem(atPath: zshCompletionPath)

                do {
                    _ = try data.write(to: URL(fileURLWithPath: zshCompletionPath), options: .atomicWrite)
                    po(tip: "【JKTool】jktool-zsh 下载成功",type: .tip)
                } catch {
                    po(tip: "【JKTool】jktool-zsh 下载失败：\n" + error.localizedDescription,type: .warning)
                }
            }

            let result = downloadTool()

            guard result else {
                return
            }

            downloadToolZshCompletion()

            let path = """
                        fpath=(\(ModulesConfigs.documentZshSharePath.replacingOccurrences(of: FileManager.userDirectory(), with: "$HOME")) $fpath)
                        export PATH="$PATH:\(ModulesConfigs.documentBinPath.replacingOccurrences(of: FileManager.userDirectory(), with: "$HOME"))"
                        """

            JKTool.append(path, userDirectoryBy: ".zshrc")

            JKTool.append(path, userDirectoryBy: ".bash_profile")

            JKTool.append(path, userDirectoryBy: ".profile")

            do {
                _ = try shellOut(to: ShellOutCommand(string: "source \(FileManager.userDirectory())/.zshrc"), at: FileManager.userDirectory())
                po(tip: "【JKTool】jktool命令注入完成")
            } catch {
                let error = error as! ShellOutError
                po(tip: "【JKTool】jktool命令注入失败：\n" + error.message + error.output,type: .warning)
            }
        }
    }

    struct Reset: ParsableCommand {
        static var configuration = CommandConfiguration(
            commandName: "reset",
            _superCommandName: "version",
            abstract: "JKTool脚本还原",
            version: "1.0.0")

        mutating func run() {

            let linkDirectoryPath = FileManager.userDirectory() + "/.JKTool"

            if !FileManager.default.fileExists(atPath: linkDirectoryPath) {
                try? FileManager.default.createDirectory(atPath: linkDirectoryPath, withIntermediateDirectories: true)
            }

            let toolLinkPath = "\(linkDirectoryPath)/jktool"
            try? FileManager.default.removeItem(atPath: toolLinkPath)


            let toolPath = ModulesConfigs.resourceBinPath + "/jktool"

            do {
                try FileManager.default.createSymbolicLink(atPath: toolLinkPath, withDestinationPath: toolPath)
                po(tip: "【JKTool】jktool link成功",type: .tip)
            } catch {
                po(tip: "【JKTool】jktool link失败：\n" + error.localizedDescription,type: .warning)
            }

            let path = """
                        fpath=(\(ModulesConfigs.resourceSharePath) $fpath)
                        export PATH="$PATH:\(ModulesConfigs.resourceBinPath)"
                        """

            JKTool.append(path, userDirectoryBy: ".zshrc")

            JKTool.append(path, userDirectoryBy: ".bash_profile")

            JKTool.append(path, userDirectoryBy: ".profile")

            do {
                _ = try shellOut(to: ShellOutCommand(string: "source \(FileManager.userDirectory())/.zshrc"), at: FileManager.userDirectory())
                po(tip: "【JKTool】jktool命令重置完成")
            } catch {
                let error = error as! ShellOutError
                po(tip: "【JKTool】jktool命令重置失败：\n" + error.message + error.output,type: .warning)
            }
        }
    }
}
